"""
游戏核心逻辑模块
包含Game类的主要游戏功能
"""

import pygame
import sys
import json
import os
from settings import *
from sprites import Player, Obstacle, Bullet, Monster

vec = pygame.math.Vector2

class Game:
    """游戏主类，负责游戏的核心逻辑"""
    
    def __init__(self):
        """初始化游戏"""
        pygame.init()
        self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
        pygame.display.set_caption(TITLE)
        self.clock = pygame.time.Clock()
        self.FPS = FPS  # 添加FPS属性
        self.dt = 0  # Delta time，用于帧率无关的移动
        self.state = 'main_menu'  # 游戏状态：main_menu, game, editor
        try:
            # 尝试使用系统中文字体
            self.font = pygame.font.SysFont('microsoftyahei', 48)
        except:
            try:
                # 如果没有微软雅黑，尝试其他中文字体
                self.font = pygame.font.SysFont('simsun', 48)
            except:
                # 如果都没有，使用默认字体（可能无法显示中文）
                self.font = pygame.font.Font(None, 48)
        self.editor_drawing = False
        self.editor_start_pos = (0, 0)
        self.current_map_file = MAP_FILE  # 当前地图文件路径
        self.game_over = False  # 游戏结束状态
        self.player_won = False  # 玩家胜利状态
        self.pathfinding_system = None  # 寻路系统
        self.player_target_path = []  # 玩家目标路径
        self.player_path_index = 0  # 玩家路径索引
        self.right_click_target = None  # 右键点击目标位置

    def new(self):
        """初始化一个新游戏"""
        self.game_over = False  # 重置游戏结束状态
        self.player_won = False  # 重置玩家胜利状态
        self.all_sprites = pygame.sprite.Group()
        self.obstacles = pygame.sprite.Group()
        self.bullets = pygame.sprite.Group()
        self.monsters = pygame.sprite.Group()  # 添加野怪精灵组
        self.player = Player(self, WIDTH / 2, HEIGHT / 2)
        self.all_sprites.add(self.player)
        # 将野怪也添加到all_sprites组中，以便统一更新
        for monster in self.monsters:
            self.all_sprites.add(monster)
        self.load_map_data()

    def run(self):
        """主游戏循环"""
        self.playing = True
        while self.playing:
            self.dt = self.clock.tick(FPS) / 1000.0
            self.events()
            self.update()
            self.draw()

    def quit(self):
        """退出游戏"""
        pygame.quit()
        sys.exit()

    def update(self):
        """游戏循环 - 更新"""
        if self.state == 'game':
            if not self.game_over:
                self.all_sprites.update()
                self.monsters.update()  # 更新野怪
                
                # 更新玩家路径移动
                self.update_player_path_movement()
                
                # 子弹与障碍物的碰撞
                pygame.sprite.groupcollide(self.bullets, self.obstacles, True, False)
                
                # 子弹与怪物的碰撞
                hits = pygame.sprite.groupcollide(self.bullets, self.monsters, True, False)
                for bullet, monsters in hits.items():
                    for monster in monsters:
                        monster.take_damage(10, self.player)  # 每次击中减少10点生命值，传入攻击者
                pygame.sprite.groupcollide(self.bullets, self.obstacles, True, False)
                
                # 检查胜利条件
                self.check_victory_condition()
    
    def check_victory_condition(self):
        """检查胜利条件：在迷雾模式下，如果所有野怪被消灭，则判定玩家胜利"""
        from settings import FOG_OF_WAR
        
        # 只在迷雾模式下检查胜利条件
        if not FOG_OF_WAR:
            return
            
        # 检查是否还有存活的野怪
        if len(self.monsters) == 0:
            # 没有野怪了，玩家胜利
            self.game_over = True
            self.player_won = True
            print("恭喜胜利！你消灭了所有野怪！")

    def update_player_path_movement(self):
        """更新玩家路径移动"""
        if (hasattr(self, 'player') and self.player.alive() and 
            self.player_target_path and self.player_path_index < len(self.player_target_path)):
            
            # 获取当前目标点
            target_point = self.player_target_path[self.player_path_index]
            
            # 计算到目标点的方向向量
            direction = pygame.math.Vector2(
                target_point[0] - self.player.pos.x,
                target_point[1] - self.player.pos.y
            )
            
            # 如果接近目标点，则移动到下一个点
            if direction.length() < 5:  # 阈值为5像素
                self.player_path_index += 1
                if self.player_path_index >= len(self.player_target_path):
                    # 已到达路径终点，停止移动
                    self.player.vel = pygame.math.Vector2(0, 0)
                    self.player_target_path = []
                    self.player_path_index = 0
                return
            
            # 标准化方向向量并设置玩家速度
            if direction.length() > 0:
                direction = direction.normalize()
                self.player.vel = direction * self.player.speed
            else:
                self.player.vel = pygame.math.Vector2(0, 0)

    def draw_grid(self):
        """在屏幕上绘制网格，用于地图编辑器"""
        for x in range(0, WIDTH, 32):
            pygame.draw.line(self.screen, LIGHTGREY, (x, 0), (x, HEIGHT))
        for y in range(0, HEIGHT, 32):
            pygame.draw.line(self.screen, LIGHTGREY, (0, y), (WIDTH, y))

    def draw_text(self, text, size, color, x, y, align="center"):
        """在屏幕上绘制文本"""
        try:
            # 尝试使用系统中文字体
            font = pygame.font.SysFont('microsoftyahei', size)
        except:
            try:
                # 如果没有微软雅黑，尝试其他中文字体
                font = pygame.font.SysFont('simsun', size)
            except:
                # 如果都没有，使用默认字体（可能无法显示中文）
                font = pygame.font.Font(None, size)
        
        text_surface = font.render(text, True, color)
        text_rect = text_surface.get_rect()
        if align == "center":
            text_rect.center = (x, y)
        elif align == "topleft":
            text_rect.topleft = (x, y)
        self.screen.blit(text_surface, text_rect)
        return text_rect  # 返回rect用于点击检测

    def draw(self):
        """游戏循环 - 绘制"""
        self.screen.fill(DARKGREY)
        if self.state == 'game':
            # 绘制障碍物（障碍物始终可见）
            self.obstacles.draw(self.screen)
            
            # 绘制玩家（玩家始终可见）
            if hasattr(self, 'player') and self.player:
                self.screen.blit(self.player.image, self.player.rect)
                self.player.draw_health_bar(self.screen)
                
                # 绘制在玩家视野内的野怪
                for monster in self.monsters:
                    if self.player.is_position_visible(monster.pos.x, monster.pos.y):
                        self.screen.blit(monster.image, monster.rect)
                        monster.draw_health_bar(self.screen)
            
            # 绘制子弹（子弹始终可见）
            self.bullets.draw(self.screen)
            
            # 应用迷雾效果
            self.apply_fog_of_war()
            
            # 如果游戏结束，显示游戏结束画面
            if self.game_over:
                # 半透明遮罩
                overlay = pygame.Surface((WIDTH, HEIGHT))
                overlay.set_alpha(128)
                overlay.fill((0, 0, 0))
                self.screen.blit(overlay, (0, 0))
                
                # 根据玩家胜利状态显示不同文本
                if self.player_won:
                    self.draw_text("恭喜胜利！你消灭了所有野怪！", 64, GREEN, WIDTH / 2, HEIGHT / 2)
                else:
                    self.draw_text("游戏结束", 64, WHITE, WIDTH / 2, HEIGHT / 2)
                self.draw_text("按ESC返回主菜单", 32, WHITE, WIDTH / 2, HEIGHT / 2 + 50)

    def events(self):
        """处理游戏主循环中的事件"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.quit()
            
            # --- 全局事件 ---
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    # 在游戏或编辑器中按ESC返回主菜单
                    if self.state in ['game', 'editor']:
                        self.state = 'main_menu'
            
            # 根据当前状态处理特定事件
            if self.state == 'game':
                self.game_events(event)

    def apply_fog_of_war(self):
        """应用迷雾效果"""
        from settings import FOG_OF_WAR
        
        # 如果不在迷雾模式下，不应用迷雾效果
        if not FOG_OF_WAR:
            return
        
        # 检查玩家是否存在
        if not hasattr(self, 'player') or not self.player:
            return
        
        # 计算玩家的视野区域
        self.player.calculate_vision_area()
        
        # 创建迷雾表面
        fog_surface = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
        fog_surface.fill((0, 0, 0, 200))  # 半透明黑色迷雾
        
        # 如果玩家有视野区域，在迷雾表面中挖出可见区域
        if self.player.visible_area and len(self.player.visible_area) > 2:
            # 如果F键被按下，显示整个填充区域
            if self.player.show_full_vision:
                # 创建一个临时表面来绘制可见区域
                visible_surface = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
                # 绘制完整的扇形区域（半透明填充）
                pygame.draw.polygon(visible_surface, (0, 0, 0, 0), self.player.visible_area)
                # 将可见区域从迷雾表面中减去
                fog_surface.blit(visible_surface, (0, 0), special_flags=pygame.BLEND_RGBA_SUB)
                
                # 在迷雾表面下方绘制扇形区域的填充颜色
                vision_surface = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
                # 使用明亮的青色半透明填充扇形区域
                pygame.draw.polygon(vision_surface, (200, 255, 255, 150), self.player.visible_area)
                # 将扇形填充绘制到屏幕上
                self.screen.blit(vision_surface, (0, 0))
                
                # 绘制扇形边界线（白色轮廓）
                center_x, center_y = self.player.pos.x, self.player.pos.y
                # 绘制扇形两侧的边界线
                pygame.draw.line(fog_surface, (255, 255, 255, 150), 
                               (center_x, center_y), self.player.visible_area[1], 2)
                pygame.draw.line(fog_surface, (255, 255, 255, 150), 
                               (center_x, center_y), self.player.visible_area[-1], 2)
            else:
                # 不按F键时，只显示两条边界线，不挖出可见区域
                center_x, center_y = self.player.pos.x, self.player.pos.y
                # 绘制扇形两侧的边界线（更明显的颜色）
                pygame.draw.line(fog_surface, (255, 255, 100, 200), 
                               (center_x, center_y), self.player.visible_area[1], 2)
                pygame.draw.line(fog_surface, (255, 255, 100, 200), 
                               (center_x, center_y), self.player.visible_area[-1], 2)
        
        # 将迷雾表面绘制到屏幕上
        self.screen.blit(fog_surface, (0, 0))

    def game_events(self, event):
        """处理游戏中的事件"""
        # 检查玩家对象是否存在
        if not hasattr(self, 'player') or not self.player:
            return

        # 玩家射击 (使用独立的 if)
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            mouse_pos = vec(pygame.mouse.get_pos())
            # 如果玩家静止，子弹就没有方向，所以加一个判断
            if (mouse_pos - self.player.pos).length_squared() > 0:
                direction = (mouse_pos - self.player.pos).normalize()
                bullet = Bullet(self, self.player.pos, direction)
                self.all_sprites.add(bullet)
                self.bullets.add(bullet)
        
        # 右键移动
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 3:
            mouse_pos = vec(pygame.mouse.get_pos())
            self.handle_player_move_click(mouse_pos)
        
        # 处理键盘按键按下事件 (使用独立的 if)
        if event.type == pygame.KEYDOWN:
            self.player.handle_key_down(event.key)
                
        # 处理键盘按键释放事件 (使用独立的 if)
        if event.type == pygame.KEYUP:
            self.player.handle_key_up(event.key)
    
    def handle_player_move_click(self, target_pos):
        """处理玩家右键移动点击"""
        # 保存目标位置
        self.right_click_target = target_pos
        
        # 如果有寻路系统，则使用寻路
        if self.pathfinding_system:
            # 计算从玩家当前位置到目标位置的路径
            path = self.pathfinding_system.find_path(
                int(self.player.pos.x), 
                int(self.player.pos.y), 
                int(target_pos.x), 
                int(target_pos.y)
            )
            
            if path:
                # 设置玩家路径
                self.player_target_path = path
                self.player_path_index = 0
                print(f"Found path with {len(path)} points")
            else:
                # 如果找不到路径，使用直线移动
                print("No path found, using direct movement")
                self.player_target_path = [target_pos]
                self.player_path_index = 0
        else:
            # 如果没有寻路系统，使用直线移动
            print("No pathfinding system, using direct movement")
            self.player_target_path = [target_pos]
            self.player_path_index = 0

    def load_map_data(self, map_file=None):
        """加载地图数据"""
        if map_file is None:
            map_file = self.current_map_file
        
        if os.path.exists(map_file):
            try:
                with open(map_file, 'r') as f:
                    data = json.load(f)
                
                # 清空现有的精灵组
                self.all_sprites.empty()
                self.obstacles.empty()
                self.bullets.empty()
                self.monsters.empty()
                
                # 重新创建玩家对象
                self.player = Player(self, WIDTH / 2, HEIGHT / 2)
                self.all_sprites.add(self.player)
                
                # 创建精灵
                for item in data:
                    if item[0] == 'obstacle':
                        obstacle = Obstacle(self, item[1], item[2], item[3], item[4])
                        self.obstacles.add(obstacle)
                        self.all_sprites.add(obstacle)
                    elif item[0] == 'monster':
                        monster = Monster(self, item[1], item[2])
                        self.monsters.add(monster)
                        self.all_sprites.add(monster)
                
                print(f"Map loaded successfully! Loaded {len(data)} items.")
                print(f"Obstacles: {len(self.obstacles)}, Monsters: {len(self.monsters)}")
                print(f"Player loaded: {hasattr(self, 'player') and self.player is not None}")
                
                # 加载寻路数据
                self.load_pathfinding_data(map_file)
            except FileNotFoundError:
                print(f"Map file {map_file} not found.")
            except json.JSONDecodeError:
                print(f"Invalid JSON format in {map_file}.")
            except Exception as e:
                print(f"Error loading map: {e}")
        else:
            print(f"Map file {map_file} does not exist.")
    
    def load_pathfinding_data(self, map_file):
        """加载寻路数据"""
        try:
            from pathfinding_system import PathfindingSystem
            self.pathfinding_system = PathfindingSystem(map_file)
            
            # 从地图数据中提取障碍物信息并创建寻路网格
            if os.path.exists(map_file):
                with open(map_file, 'r') as f:
                    data = json.load(f)
                
                # 提取障碍物位置信息
                blocked_tiles = []
                for item in data:
                    if item[0] == 'obstacle':
                        x, y, width, height = item[1], item[2], item[3], item[4]
                        
                        # 考虑玩家大小（30x30），让障碍物外扩相当于玩家半径（9像素）的范围
                        player_radius = 9
                        x_expanded = max(0, x - player_radius)
                        y_expanded = max(0, y - player_radius)
                        width_expanded = width + player_radius * 2
                        height_expanded = height + player_radius * 2
                        
                        # 将障碍物区域转换为网格坐标
                        grid_x_start = max(0, min(WIDTH // 10 - 1, x_expanded // 10))
                        grid_y_start = max(0, min(HEIGHT // 10 - 1, y_expanded // 10))
                        grid_x_end = max(0, min(WIDTH // 10 - 1, (x_expanded + width_expanded) // 10))
                        grid_y_end = max(0, min(HEIGHT // 10 - 1, (y_expanded + height_expanded) // 10))
                        
                        # 标记障碍物区域内的所有网格点
                        for grid_x in range(grid_x_start, grid_x_end + 1):
                            for grid_y in range(grid_y_start, grid_y_end + 1):
                                blocked_tiles.append((grid_x, grid_y))
                
                # 创建寻路网格
                grid_width = WIDTH // 10
                grid_height = HEIGHT // 10
                self.pathfinding_system.create_grid_from_map([], blocked_tiles, grid_width, grid_height)
                print(f"Pathfinding grid created: {grid_width}x{grid_height} with {len(blocked_tiles)} blocked tiles")
            
            self.pathfinding_system.load_pathfinding_data()
            print(f"Pathfinding data loaded for {map_file}")
        except Exception as e:
            print(f"Error loading pathfinding data: {e}")
            self.pathfinding_system = None

    def get_map_files(self):
        """获取所有地图文件"""
        if not os.path.exists(MAPS_DIR):
            os.makedirs(MAPS_DIR)
            return []
        
        map_files = []
        for file in os.listdir(MAPS_DIR):
            if file.endswith('.json'):
                map_files.append(file)
        return map_files